Skip to content
This repository was archived by the owner on Aug 11, 2025. It is now read-only.

Implement switch statements and expressions#9

Open
AlexisMardas wants to merge 1 commit intoRandgalt:masterfrom
HliasMpGH:switch
Open

Implement switch statements and expressions#9
AlexisMardas wants to merge 1 commit intoRandgalt:masterfrom
HliasMpGH:switch

Conversation

@AlexisMardas
Copy link

** SECOND PART OF ISSUE #5 **

This feature enables the use of traditional switch statements and extended switch expressions within CodeBlocks and MethodSpecs. The necessary testing has also been conducted.

Now let's have a look at the code necessary to create a simple method that contains a switch statement. The following code:

// Create a method that includes a simple switch statement
      MethodSpec method = MethodSpec.methodBuilder("example")
      .addParameter(TypeName.INT, "x")
      .beginSwitchStatement("x")
      .addSwitchCase(true,"$L, $L, $L", 1, 2, 3)
      .addCode(CodeBlock.of("doSomething();\nbreak;\n"))
      .addSwitchCase(false, CodeBlock.of("$L", 4))
      .addCode(CodeBlock.of("doSomethingeElse();\nbreak;\n"))
      .addDefaultCase()
      .addCode(CodeBlock.of("doDefaultOperation();\nbreak;\n"))
      .endSwitchStatement(false)
      .build();

Generates this output:

void example(int x) {
  switch (x) {
    case 1, 2, 3:
      doSomething();
      break;
    case 4:
      doSomethingeElse();
      break;
    default:
      doDefaultOperation();
      break;
  }
}

As you can see the methods implemented follow the logic of the already existing ones that are used to generate control flows, but are specifically created to accomodate switch statement generation.

Now let's have a look at another example, that showcases the code necessary to create a CodeBlock that consists of an extended switch expression. The following code:

// For this example, the java.time.DayOfWeek enum is being used
      CodeBlock cb = CodeBlock.builder()
      .addStatement("$T day", java.time.DayOfWeek.class)
      .add("$T dailyTask = ", String.class)
      .beginSwitchStatement("day")
      .addExtendedSwitchCase(CodeBlock.of("$S;", "Attend meeting"), "$L, $L", DayOfWeek.MONDAY, DayOfWeek.TUESDAY)
      .addExtendedSwitchCase(CodeBlock.of("$S;", "Business trip"), "$L, $L", DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY)
      .addExtendedSwitchCase(CodeBlock.of("$S;", "Office work"), "$L", DayOfWeek.FRIDAY)
      .addExtendedDefaultCase(CodeBlock.of("$S;", "Relax"))
      .endSwitchStatement(true)
      .build();

Can be used to generate this output:

java.time.DayOfWeek day;
java.lang.String dailyTask = switch (day) {
  case MONDAY, TUESDAY -> "Attend meeting";
  case WEDNESDAY, THURSDAY -> "Business trip";
  case FRIDAY -> "Office work";
  default -> "Relax";
}

It should be noted that if the body of each case included more than one lines or statements, then it would be automatically enclosed in braces.

The entire feature relies heavily on the already used placeholder mechanism of the project, both to remain consistent with the rest of the codebase and to provide users with the flexibility required to create switch statements and expressions. Where necessary, method overloads have also been implemented.

* @param args the values to be placed instead of the format's placeholders
*/
public Builder beginSwitchStatement(String expressionFormat, Object... args) {
add("switch ("+expressionFormat+") {\n", args);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must not assume where newlines, indenting, tabs, etc. go. The library already has mechanisms for users to specify these.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The already existing methods that implement control flows do the same thing, adding newlines and adjusting the indentation. I tried to be consistent with the codebase and create methods that follow the same logic. If that's a problem would you suggest I simply remove newline characters?

// If the body contains multiple lines or expressions it should be
// contained in braces
if (bodySide.lines().count() > 1 || bodySide.split(";").length > 1) {
bodySide = "{ " + bodySide + " }";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is coming up in the lambda PR too. We need a general way for users to specify how to output lambda-like code bodies. We can't assume how the braces are positioned around the code block.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you suggest I tackle this issue? Would simply removing these lines of code and assuming that the user includes the braces in the code block when necessary resolve the problem?

Copy link
Owner

@Randgalt Randgalt Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I just wrote in the lambda PR, I'd like to see a new builder class shared by both lambda and this PR that is similar to CodeBlock. Users should be able to specify exactly (and in detail) how newlines, indents, etc. are generated.

i.e.

Some people will want:

switch (foo) {
  case X -> { yield 10; }
}

Some will want:

switch (foo) {
  case X -> 
  { yield 10; 
  }
}

Some will want:

switch (foo) {
  case X -> { 
    yield 10; 
  }
}

And every variation inbetween

@Randgalt
Copy link
Owner

Randgalt commented Jun 2, 2024

I'm having a hard time keeping up with reviews on this project. Do you know anyone else who can help review?

@Randgalt
Copy link
Owner

Please see: #16 - let's use that class as a basis for switch (or vice versa). Work with @HliasMpGH to come up with a generalization. Switch expressions and lambdas are nearly identical in terms of bodies.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants